package com.nuoniu.sibanyun.service.production.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nuoniu.sibanyun.common.exception.NuoNiuException;
import com.nuoniu.sibanyun.common.lang.StringUtils;
import com.nuoniu.sibanyun.entity.dto.BarcodeMainInfoSearchDto;
import com.nuoniu.sibanyun.entity.dto.ErpWorkProcedureCardDetailDto;
import com.nuoniu.sibanyun.entity.dto.WorkProcedureReportDto;
import com.nuoniu.sibanyun.entity.erp.ErpProcessRouteDetail;
import com.nuoniu.sibanyun.entity.erp.ErpWorkProcedure;
import com.nuoniu.sibanyun.entity.production.ErpWorkProcedureCardDetail;
import com.nuoniu.sibanyun.entity.erp.barcode.ErpBarcodeMainInfo;
import com.nuoniu.sibanyun.entity.erp.in.InInventory;
import com.nuoniu.sibanyun.entity.production.*;
import com.nuoniu.sibanyun.entity.vo.*;
import com.nuoniu.sibanyun.mapper.production.ErpWorkProcedureCardDetailMapper;
import com.nuoniu.sibanyun.service.erp.*;
import com.nuoniu.sibanyun.service.erp.barcode.IErpBarcodeMainInfoService;
import com.nuoniu.sibanyun.service.erp.in.IInInventoryService;
import com.nuoniu.sibanyun.service.production.*;
import com.nuoniu.sibanyun.service.production.IErpWorkProcedureCardDetailService;
import com.nuoniu.sibanyun.userThread.UserInfo;
import com.nuoniu.sibanyun.userThread.UserThreadLocal;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 工序流转卡明细 服务实现类
 * </p>
 *
 * @author 白强
 * @since 2021-03-30
 */
@Service
@Log4j2
public class ErpWorkProcedureCardDetailServiceImpl extends ServiceImpl<ErpWorkProcedureCardDetailMapper, ErpWorkProcedureCardDetail> implements IErpWorkProcedureCardDetailService {


    @Autowired
    private IVProductionWorkMainService productionWorkMainService;
    @Autowired
    private IVProductionWorkDetailService productionWorkDetailService;
    @Autowired
    private IErpProcessRouteService processRouteService;
    @Autowired
    private IErpProcessRouteDetailService processRouteDetailService;
    @Autowired
    private IVProductionWorkProcedureDetailService productionWorkProcedureDetailService;
    @Autowired
    private IErpAccountService erpAccountService;
    @Autowired
    private IErpWorkProcedureService erpWorkProcedureService;
    @Autowired
    private IVProductionDispatchMainService productionDispatchMainService;
    @Autowired
    private IVProductionFinishMainService productionFinishMainService;
    @Autowired
    private IVProductionFinishDetailService productionFinishDetailService;
    @Autowired
    private IInInventoryService inInventoryService;
    @Autowired
    private IVProcedurePriceDetailService procedurePriceDetailService;
    @Autowired
    private IErpBarcodeMainInfoService barcodeMainInfoService;

    /**
     * 新建 工序汇报
     * @param erpWorkProcedureCardDetail
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void createCardDetail(ErpWorkProcedureCardDetail erpWorkProcedureCardDetail,String reportCode) {
        UserInfo userInfo = UserThreadLocal.get();
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        Long id = erpWorkProcedureCardDetail.getId();
        ErpWorkProcedureCardDetail oldCardDetail = null;
        BigDecimal oldReportQuantity = null;
        if (null != id){
            oldCardDetail = getById(id);
            oldReportQuantity = oldCardDetail.getQualifiedQuantity().add(oldCardDetail.getReworkQuantity());
            if( null != oldCardDetail){
//                reportCode = oldCardDetail.getReportCode();
                erpWorkProcedureCardDetail.setProductionWorkMainId(oldCardDetail.getProductionWorkMainId());
                erpWorkProcedureCardDetail.setProductionWorkDetailId(oldCardDetail.getProductionWorkDetailId());
                erpWorkProcedureCardDetail.setInventoryId(oldCardDetail.getInventoryId());
                erpWorkProcedureCardDetail.setProcedureId(oldCardDetail.getProcedureId());
            }
        }
        /** 获取加工单信息 */
        VProductionWorkMain productionWorkMain = productionWorkMainService.getById(erpWorkProcedureCardDetail.getProductionWorkMainId());
        /** 产品生产数量 */
        Integer productionWorkDetailId = erpWorkProcedureCardDetail.getProductionWorkDetailId();
        VProductionWorkDetail productionWorkDetail = productionWorkDetailService.getById(productionWorkDetailId);
        BigDecimal productionWorkDetailBaseQuantity = productionWorkDetail.getBaseQuantity();
        /** TODO 设置汇报工人信息 */
//        erpWorkProcedureCardDetail.setWorkerId(userInfo.getUserId());
        erpWorkProcedureCardDetail.setCompanyId(userInfo.getCompanyId());
        erpWorkProcedureCardDetail.setAccountId(currentAccountId);
        erpWorkProcedureCardDetail.setStatus(0);

        // 当前 合格 数量
        BigDecimal currentQualifiedQuantity = erpWorkProcedureCardDetail.getQualifiedQuantity();
        // 返工数量
        BigDecimal currentReworkQuantity = erpWorkProcedureCardDetail.getReworkQuantity();
        // 当前 不合格数量
        BigDecimal currentUnqualifiedQuantity = erpWorkProcedureCardDetail.getUnqualifiedQuantity();
        //当前 报废数量
        BigDecimal currentScrapQuantity = erpWorkProcedureCardDetail.getScrapQuantity();
        if(null == currentQualifiedQuantity)throw new NuoNiuException("请填写合格数量");
        if(null == currentReworkQuantity)throw new NuoNiuException("请填写返工数量");
        if(null == currentUnqualifiedQuantity)throw new NuoNiuException("请填写不合格数量");
        if(null == currentScrapQuantity)throw new NuoNiuException("请填写报废数量");
        if(currentQualifiedQuantity.add(currentReworkQuantity).add(currentUnqualifiedQuantity).add(currentScrapQuantity).compareTo(BigDecimal.ZERO) == 0){
            throw new NuoNiuException("请填写汇报数量");
        }
        // 本次上报数量（ 合格 + 返工）
        BigDecimal reportQuantity = currentQualifiedQuantity.add(currentReworkQuantity);

        /**当前加工单工序执行详情 */
        Integer productionWorkProcedureDetailId = erpWorkProcedureCardDetail.getProductionWorkProcedureDetailId();
        VProductionWorkProcedureDetailVo vProductionWorkProcedureDetailVo = productionWorkProcedureDetailService.getVProductionWorkProcedureDetailVo(productionWorkProcedureDetailId);
        if (null == vProductionWorkProcedureDetailVo)throw new NuoNiuException("参数错误,请重新选择");
        Integer status = vProductionWorkProcedureDetailVo.getStatus();
        if(1 == status )throw new NuoNiuException("该工序已经中止汇报");
        if(10 == status && null == oldCardDetail)throw new NuoNiuException("该工序已经完成汇报");
        // 工序标识1:首工序2:尾工序3:中间工序
        Integer workFlag = vProductionWorkProcedureDetailVo.getWorkFlag();
        // 加工顺序
        Integer workOrder = vProductionWorkProcedureDetailVo.getWorkOrder();
        //当前加工单工序执行详情--- 累计合格数量
        BigDecimal cumQualifiedQuantity = vProductionWorkProcedureDetailVo.getCumQualifiedQuantity();
        if (null == cumQualifiedQuantity)cumQualifiedQuantity = new BigDecimal(0);
        //当前加工单工序执行详情--- 累计不合格数量
        BigDecimal cumUnqualifiedQuantity = vProductionWorkProcedureDetailVo.getCumUnqualifiedQuantity();
        if (null == cumUnqualifiedQuantity)cumUnqualifiedQuantity = new BigDecimal(0);
        //当前加工单工序执行详情--- 累计返工数量
        BigDecimal cumReworkQuantity = vProductionWorkProcedureDetailVo.getCumReworkQuantity();
        if (null == cumReworkQuantity)cumReworkQuantity = new BigDecimal(0);
        //当前加工单工序执行详情--- 累计报废数量
        BigDecimal cumScrapQuantity = vProductionWorkProcedureDetailVo.getCumScrapQuantity();
        if (null == cumScrapQuantity)cumScrapQuantity = new BigDecimal(0);
        //当前加工单工序执行详情--- 累计上报数量
        BigDecimal totalReportQuantity = cumQualifiedQuantity.add(cumReworkQuantity);

        VProductionWorkProcedureDetail vProductionWorkProcedureDetail = new VProductionWorkProcedureDetail();
        /**  ************* 数量校验原则-开始 ***************
         * 本工序的累计上报数量上限，受上工序累计合格数量限制( 首工序不受影响 ) ；
        */
        //本次上报数量后，累计上报数量
        BigDecimal currentFinalReportQuantity = totalReportQuantity.add(reportQuantity);

        if (null != oldCardDetail && null != oldReportQuantity){
            currentFinalReportQuantity = currentFinalReportQuantity.subtract(oldReportQuantity);
        }
        if (productionWorkDetailBaseQuantity.compareTo(currentFinalReportQuantity) <= 0){
            /**   更新 本次派工单下 所有相同工序的任务状态    */
//            productionWorkProcedureDetailService.batchUpdateStatus(vProductionWorkProcedureDetailVo.getProductionDispatchId(),vProductionWorkProcedureDetailVo.getProcessRouteDetailId(),10);
        }else {
            if (null != oldCardDetail){
//                productionWorkProcedureDetailService.batchUpdateStatus(vProductionWorkProcedureDetailVo.getProductionDispatchId(),vProductionWorkProcedureDetailVo.getProcessRouteDetailId(),0);
            }
        }
        /**  ************* 数量校验原则-结束 ***************

        /** 更新 本次工序 执行情况*/
        vProductionWorkProcedureDetail.setId(vProductionWorkProcedureDetailVo.getId());
        cumQualifiedQuantity = cumQualifiedQuantity.add(currentQualifiedQuantity);
        cumUnqualifiedQuantity = cumUnqualifiedQuantity.add(currentUnqualifiedQuantity);
        cumReworkQuantity = cumReworkQuantity.add(currentReworkQuantity);
        cumScrapQuantity = cumScrapQuantity.add(currentScrapQuantity);
        // 如果是修改，累加之后 再减去以前
        if ( null != oldCardDetail ){
            cumQualifiedQuantity = cumQualifiedQuantity.subtract(oldCardDetail.getQualifiedQuantity());
            cumUnqualifiedQuantity = cumUnqualifiedQuantity.subtract(oldCardDetail.getUnqualifiedQuantity());
            cumReworkQuantity = cumReworkQuantity.subtract(oldCardDetail.getReworkQuantity());
            cumScrapQuantity = cumScrapQuantity.subtract(oldCardDetail.getScrapQuantity());
        }
        vProductionWorkProcedureDetail.setCumQualifiedQuantity(cumQualifiedQuantity);
        vProductionWorkProcedureDetail.setCumUnqualifiedQuantity(cumUnqualifiedQuantity);
        vProductionWorkProcedureDetail.setCumReworkQuantity(cumReworkQuantity);
        vProductionWorkProcedureDetail.setCumScrapQuantity(cumScrapQuantity);
        productionWorkProcedureDetailService.updateById(vProductionWorkProcedureDetail);
        //如果是尾工序 更新派工单完成数

        //尾工序
        if (2 == workFlag){
            /** 计算 加工单明细 已完成数量 */
            //已完成数量
            BigDecimal finishInventoryQuantity = productionWorkDetail.getCumExecuteQuantity();
            if (null == finishInventoryQuantity){
                finishInventoryQuantity = new BigDecimal(0);
            }
            finishInventoryQuantity = finishInventoryQuantity.add(currentQualifiedQuantity).add(currentReworkQuantity);
            if (null != oldCardDetail){
                finishInventoryQuantity = finishInventoryQuantity.subtract(oldCardDetail.getQualifiedQuantity()).subtract(oldCardDetail.getReworkQuantity());
            }
            if (finishInventoryQuantity.compareTo(productionWorkDetailBaseQuantity) > 0)throw new NuoNiuException("累计完工数量不能超过生产数量");
        }
        /** 计算工资 */
        // 工资类型1:计件2:计时3:不核算
        Integer wagesType = vProductionWorkProcedureDetailVo.getWagesType();

        BigDecimal qualifiedPrice;
        BigDecimal reworkPrice;
        BigDecimal scrapPrice;
        BigDecimal unqualifiedPrice;
        VProcedurePriceDetail procedurePriceDetail = procedurePriceDetailService.getByProductionIdAndRouteDetailId(vProductionWorkProcedureDetailVo.getParentInventoryId(), vProductionWorkProcedureDetailVo.getProcessRouteDetailId());
        if( null != procedurePriceDetail){
            qualifiedPrice = procedurePriceDetail.getQualifiedPrice();
            reworkPrice = procedurePriceDetail.getReworkPrice();
            scrapPrice = procedurePriceDetail.getScrapPrice();
            unqualifiedPrice = procedurePriceDetail.getUnqualifiedPrice();
        }else {
            // 获取 工序详情
            ErpWorkProcedure erpWorkProcedure = erpWorkProcedureService.getById(erpWorkProcedureCardDetail.getProcedureId());
            qualifiedPrice = erpWorkProcedure.getQualifiedPrice();
            reworkPrice = erpWorkProcedure.getReworkPrice();
            scrapPrice = erpWorkProcedure.getScrapPrice();
            unqualifiedPrice = erpWorkProcedure.getUnqualifiedPrice();
        }
        erpWorkProcedureCardDetail.setQualifiedPrice(qualifiedPrice);
        erpWorkProcedureCardDetail.setReworkPrice(qualifiedPrice);
        erpWorkProcedureCardDetail.setScrapPrice(qualifiedPrice);
        erpWorkProcedureCardDetail.setWagesType(wagesType);
        if (null != wagesType){
            // 1.计件
            if (1 == wagesType){

                BigDecimal workerWages = new BigDecimal(0);
                if(null != qualifiedPrice){
                    workerWages = workerWages.add(qualifiedPrice.multiply(currentQualifiedQuantity));
                }
                if (null != reworkPrice){
                    workerWages = workerWages.add(reworkPrice.multiply(currentReworkQuantity));
                }
                if (null != scrapPrice){
                    workerWages = workerWages.add(scrapPrice.multiply(currentUnqualifiedQuantity));
                }
                if (null != unqualifiedPrice){
                    workerWages = workerWages.add(unqualifiedPrice.multiply(currentUnqualifiedQuantity));
                }
                erpWorkProcedureCardDetail.setWorkerWages(workerWages);
            }
            else if(2 == wagesType){
                BigDecimal workHour = erpWorkProcedureCardDetail.getWorkHour();
                BigDecimal workerWages = new BigDecimal(0);
                if (null == workHour)throw new NuoNiuException("请填报工时");
                if(null != qualifiedPrice && null != workHour){
                    workerWages = workerWages.add(qualifiedPrice.multiply(workHour));
                }
                erpWorkProcedureCardDetail.setWorkerWages(workerWages);
            }
        }
//        /**  生成汇报单号 1.查询最新的流水号 2.汇报单号 = 派工单号 +  流水号 */
//        if(StringUtils.isBlank(reportCode)){
//            getAndSetReportCode(erpWorkProcedureCardDetail,erpWorkProcedureCardDetail.getProductionWorkProcedureDetailId(), productionWorkMain.getVoucherCode());
//        }else{
//            erpWorkProcedureCardDetail.setReportCode(reportCode);
//        }
        /**  校验 是否 尾工序 执行完毕  */

        /** 保存工序任务单 */
        saveOrUpdate(erpWorkProcedureCardDetail);
        /**如果是尾工序， 是否自动生成 生成完工单 */
        if (2 == workFlag ){
            //查询 是否生成 完工单
            this.saveVProductionFinishMainFromCardDetail(erpWorkProcedureCardDetail);
        }
    }

    /**
     * 工序汇报生成 完工单
     * @param erpWorkProcedureCardDetail
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void saveVProductionFinishMainFromCardDetail(ErpWorkProcedureCardDetail erpWorkProcedureCardDetail) {
        BigDecimal qualifiedQuantity = erpWorkProcedureCardDetail.getQualifiedQuantity();
        BigDecimal reworkQuantity = erpWorkProcedureCardDetail.getReworkQuantity();
        BigDecimal currentFinishQuantity = qualifiedQuantity.add(reworkQuantity);
        //1.查询 完工单 信息
        VProductionFinishMain vProductionFinishMain = productionFinishMainService.getByCardDetailId(erpWorkProcedureCardDetail.getId());
        if( null != vProductionFinishMain){
            Integer voucherState = vProductionFinishMain.getVoucherState();

            if (voucherState > 0)throw new NuoNiuException("尾工序汇报记录生产的完工单已经审核，不能修改");
            //2.查询 完工单 明细
            List<VProductionFinishDetail> vProductionFinishDetails = productionFinishDetailService.listByMainId(vProductionFinishMain.getId());

            if (null == vProductionFinishDetails || vProductionFinishDetails.size() != 1)throw new NuoNiuException("尾工序汇报记录生产的完工单明细错误");
            VProductionFinishDetail vProductionFinishDetail = vProductionFinishDetails.get(0);
            vProductionFinishDetail.setBaseQuantity(currentFinishQuantity); //完成数量
            vProductionFinishDetail.setReturnQuantity(reworkQuantity);  //返工数量
            vProductionFinishDetail.setUnqualifiedQuantity(erpWorkProcedureCardDetail.getUnqualifiedQuantity()); //不合格数量
            vProductionFinishMain.setTotalQuantity(currentFinishQuantity);

            productionFinishMainService.saveOrUpdate(vProductionFinishMain);
            productionFinishDetailService.saveOrUpdate(vProductionFinishDetail);
            return;
        }
        vProductionFinishMain = new VProductionFinishMain();
        //4.查询 产品 计量单位信息
        InInventory inInventory = inInventoryService.getById(erpWorkProcedureCardDetail.getInventoryId());
        List<VProductionFinishDetail> orderDetailList = new ArrayList<>();
        VProductionFinishDetail productionFinishDetail = new VProductionFinishDetail();
        orderDetailList.add(productionFinishDetail);
        vProductionFinishMain.setOrderDetailList(orderDetailList);

        Integer productionWorkDetailId = erpWorkProcedureCardDetail.getProductionWorkDetailId();
        if(null != productionWorkDetailId){
            VProductionWorkMain productionWorkMain = productionWorkMainService.getById(erpWorkProcedureCardDetail.getProductionWorkMainId());

            vProductionFinishMain.setSourceVoucherType("ProductionWork");
            vProductionFinishMain.setSourceVoucherId(productionWorkMain.getId().intValue());
            vProductionFinishMain.setSourceVoucherCode(productionWorkMain.getVoucherCode());
            vProductionFinishMain.setSourceVoucherDate(productionWorkMain.getVoucherDate());
            vProductionFinishMain.setOfficeId(productionWorkMain.getOfficeId());
            vProductionFinishMain.setOfficeName(productionWorkMain.getOfficeName());

            productionFinishDetail.setSourceVoucherType("ProductionWork");
            productionFinishDetail.setSourceVoucherId(productionWorkMain.getId().intValue());
            productionFinishDetail.setSourceVoucherCode(productionWorkMain.getVoucherCode());
            productionFinishDetail.setSourceVoucherDate(productionWorkMain.getVoucherDate());
            productionFinishDetail.setProductionOrderCode(productionWorkMain.getVoucherCode());
            productionFinishDetail.setOfficeId(productionWorkMain.getOfficeId());
            productionFinishDetail.setOfficeName(productionWorkMain.getOfficeName());
        }

        vProductionFinishMain.setVoucherDate(LocalDate.now());
        vProductionFinishMain.setBusinessType(0);
        vProductionFinishMain.setWorkProcedureCardDetailId(erpWorkProcedureCardDetail.getId());
//        vProductionFinishMain.setWorkProcedureCardDetailCode(erpWorkProcedureCardDetail.getReportCode());


        productionFinishDetail.setInventoryId(erpWorkProcedureCardDetail.getInventoryId().intValue());
        productionFinishDetail.setInventoryCode(inInventory.getInventoryCode());
        productionFinishDetail.setInventoryName(inInventory.getInventoryName());
        productionFinishDetail.setInventorySpecification(inInventory.getInventorySpecification());
        productionFinishDetail.setBaseQuantity(currentFinishQuantity);
        productionFinishDetail.setQualifiedQuantity(qualifiedQuantity);
        productionFinishDetail.setReturnQuantity(reworkQuantity);
        productionFinishDetail.setUnqualifiedQuantity(erpWorkProcedureCardDetail.getUnqualifiedQuantity());
        productionFinishDetail.setSourceDetailId(productionWorkDetailId);

        if ("单计量".equals(inInventory.getUnitType())){
            productionFinishDetail.setUnitId(inInventory.getUnitId());
            productionFinishDetail.setBaseUnit(inInventory.getUnitId());
            productionFinishDetail.setBaseUnitName(inInventory.getUnitName());
        }else{
            productionFinishDetail.setUnitGroupId(inInventory.getUnitGroupId());
            productionFinishDetail.setBaseUnit(inInventory.getMainUnit());
            productionFinishDetail.setBaseUnitName(inInventory.getMainUnitName());
        }
        productionFinishDetail.setBatchNo(erpWorkProcedureCardDetail.getBatchNo());
        productionFinishDetail.setTeamId(erpWorkProcedureCardDetail.getTeamId());
        productionFinishDetail.setTeamName(erpWorkProcedureCardDetail.getTeamName());
        productionFinishDetail.setRemarks(erpWorkProcedureCardDetail.getRemarks());
        productionFinishMainService.saveOrder(vProductionFinishMain);

    }

    /**
     * 分页查询 已经提交的 工序汇报
     * @return
     */
    @Override
    public Page<ErpWorkProcedureCardDetailVo> pageErpWorkProcedureCardDetailVo(Page page, ErpWorkProcedureCardDetailDto erpWorkProcedureCardDetailDto) {
        UserInfo userInfo = UserThreadLocal.get();
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        Page<ErpWorkProcedureCardDetailVo> erpWorkProcedureCardDetailVoPage = baseMapper.pageProductionWorkProcedureDetailVo(page, userInfo.getCompanyId(),currentAccountId, erpWorkProcedureCardDetailDto);
        return erpWorkProcedureCardDetailVoPage;
    }

    @Override
    public boolean checkWorkReport(Long mainId) {
        UserInfo userInfo = UserThreadLocal.get();
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        return baseMapper.checkWorkReport(userInfo.getCompanyId(), currentAccountId, mainId);
    }

    @Override
    public boolean checkWorkReportByWorkDetailIds(List<Long> workDetailIds) {
        UserInfo userInfo = UserThreadLocal.get();
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        return baseMapper.checkWorkReportByWorkDetailIds(userInfo.getCompanyId(),currentAccountId,workDetailIds);
    }





    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void batchSaveCardDetail(List<ErpWorkProcedureCardDetail> erpWorkProcedureCardDetailList) {
        if ( null == erpWorkProcedureCardDetailList || erpWorkProcedureCardDetailList.size() == 0)throw new NuoNiuException("上报记录不能为空");
        ErpWorkProcedureCardDetail firstErpWorkProcedureCardDetail = erpWorkProcedureCardDetailList.get(0);
        Long productionWorkMainId = firstErpWorkProcedureCardDetail.getProductionWorkMainId();
        VProductionWorkMain productionWorkMain = productionWorkMainService.getById(productionWorkMainId);
        Integer productionWorkDetailId = firstErpWorkProcedureCardDetail.getProductionWorkDetailId();
        UserInfo userInfo = UserThreadLocal.get();
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        Integer maxSerialNumber = baseMapper.getMaxSerialNumber(userInfo.getCompanyId(), currentAccountId, productionWorkDetailId);
        if(null == maxSerialNumber)maxSerialNumber = 0;
        for (int i = 0; i < erpWorkProcedureCardDetailList.size(); i++) {
            ErpWorkProcedureCardDetail erpWorkProcedureCardDetail = erpWorkProcedureCardDetailList.get(i);
            Integer serialNumber = maxSerialNumber + i + 1;
            String reportCode = productionWorkMain.getVoucherCode() + String.format("%04d", serialNumber);
           log.debug("批量汇报工序maxSerialNumber：{},i:{},reportCode:{}",maxSerialNumber,i,reportCode);
            erpWorkProcedureCardDetail.setSerialNumber(serialNumber);
            createCardDetail(erpWorkProcedureCardDetail,reportCode);
        }
    }

    /**
     * 批量提交条码 汇报工序  // TODO 去掉 派工单 单据
     * @param workProcedureReportDto
     */
    @Override
    // TODO 去掉 派工单 单据
    public WorkProcedureReportResult batchSaveCardDetail(WorkProcedureReportDto workProcedureReportDto) {
        /** 工艺路线明细ID */
        Integer erpProcessRouteDetailId = workProcedureReportDto.getErpProcessRouteDetailId();
        ErpProcessRouteDetail processRouteDetail = processRouteDetailService.getById(erpProcessRouteDetailId);
        if(null == processRouteDetail)throw new NuoNiuException("汇报工序失败，查询不到工艺明细");
        UserInfo userInfo = UserThreadLocal.get();
        LocalDateTime now = LocalDateTime.now();
        WorkProcedureReportResult reportResult = new WorkProcedureReportResult();
        /** 1. 条码 解析*/
        BarcodeMainInfoSearchDto barcodeMainInfoSearchDto = new BarcodeMainInfoSearchDto();
        barcodeMainInfoSearchDto.setBarcode(workProcedureReportDto.getBarcodeStr());
        List<ErpBarcodeMainInfo> erpBarcodeMainInfoList = barcodeMainInfoService.analysisByBarCode(barcodeMainInfoSearchDto);
        if(erpBarcodeMainInfoList.size() == 0)throw new NuoNiuException("无效条码");
        /** 校验 条码 是否 来自  加工单明细 （无效条码）*/
        String[] split = workProcedureReportDto.getBarcodeStr().split(",");
        List<String> orgBarcodes = new ArrayList<>(Arrays.asList(split));
        List<String> matchBarcodes = erpBarcodeMainInfoList.stream().filter(f -> f.getSourceVoucherType().equals("ProductionWork")).map(ErpBarcodeMainInfo::getBarCode).collect(Collectors.toList());
        orgBarcodes.removeAll(matchBarcodes);
        reportResult.setNotMatchCodes(orgBarcodes);
        List<String> failMatchCodes = new ArrayList<>();
        List<String> successMatchCodes = new ArrayList<>();
        reportResult.setFailMatchCodes(failMatchCodes);
        reportResult.setSuccessMatchCodes(successMatchCodes);

        /** 2. 查询 源单据 数据*/
        erpBarcodeMainInfoList.stream().forEach(item->{
            String barCode = item.getBarCode();
            try {
                // 获取 源单明细id
                Integer sourceDetailId = item.getSourceDetailId();
                //获取加工单明细
                VProductionWorkDetail workDetail = productionWorkDetailService.getById(sourceDetailId);
                //查询 是否生成 派工单
                VProductionDispatchMainVo productionDispatchMainVo = productionDispatchMainService.getByProductionWorkDetailId(sourceDetailId);
                VProductionDispatchMain vProductionDispatchMain = productionDispatchMainVo.getVProductionDispatchMain();
                /** */
                if(null == vProductionDispatchMain){
                    Integer processRouteId = workDetail.getProcessRouteId();
                    if(processRouteId != processRouteDetail.getPrId())throw new NuoNiuException("当前工序，与产品的工艺线路不匹配");
                    Integer workMainId = workDetail.getOrderId();
                    //获取加工单主表
                    VProductionWorkMain productionWorkMain = productionWorkMainService.getById(workMainId);
                    //获取加工单明细 产品 的工艺路线
                    List<ErpProcessRouteDetail>  erpProcessRouteDetails = processRouteService.getDetailList(processRouteId);
                    //生成 派工单主表
                    VProductionDispatchMain newVProductionDispatchMain = new VProductionDispatchMain();
                    newVProductionDispatchMain.setProductionWorkMainId(workMainId);
                    newVProductionDispatchMain.setProductionWorkDetailId(sourceDetailId);
                    newVProductionDispatchMain.setProductionWorkCode(productionWorkMain.getVoucherCode());
                    newVProductionDispatchMain.setOfficeId(productionWorkMain.getOfficeId());
                    newVProductionDispatchMain.setOfficeName(productionWorkMain.getOfficeName());
                    newVProductionDispatchMain.setInventoryId(workDetail.getInventoryId());
                    newVProductionDispatchMain.setInventoryCode(workDetail.getInventoryCode());
                    newVProductionDispatchMain.setInventoryName(workDetail.getInventoryName());
                    newVProductionDispatchMain.setInventoryBarCode(workDetail.getInventoryBarCode());
                    newVProductionDispatchMain.setProcessRouteId(processRouteId);
                    newVProductionDispatchMain.setProcessRouteName(workDetail.getProcessRouteName());
                    newVProductionDispatchMain.setBomId(workDetail.getBomId());
                    newVProductionDispatchMain.setBomName(workDetail.getBomName());
                    newVProductionDispatchMain.setBaseUnit(workDetail.getBaseUnit());
                    newVProductionDispatchMain.setBaseUnitName(workDetail.getBaseUnitName());
                    newVProductionDispatchMain.setTotalInventoryQuantity(workDetail.getBaseQuantity());
                    newVProductionDispatchMain.setDispatchInventoryQuantity(workDetail.getBaseQuantity());
                    newVProductionDispatchMain.setDispatchTimes(1);
                    newVProductionDispatchMain.setVoucherDate(now.toLocalDate());
                    newVProductionDispatchMain.setDispatchDate(now.toLocalDate());
                    newVProductionDispatchMain.setVoucherState(1);
                    //生成 派工明细表
                    List<VProductionWorkProcedureDetail> procedureDetails = new ArrayList<>();
                    erpProcessRouteDetails.forEach(routeDetail->{
                        VProductionWorkProcedureDetail newVProductionWorkProcedureDetail = new VProductionWorkProcedureDetail();
                        newVProductionWorkProcedureDetail.setWorkerId(userInfo.getUserId());
                        newVProductionWorkProcedureDetail.setWorkerName(userInfo.getBankName());
                        newVProductionWorkProcedureDetail.setParentInventoryId(workDetail.getInventoryId());
                        newVProductionWorkProcedureDetail.setStartDate(now.toLocalDate());
                        newVProductionWorkProcedureDetail.setProcessRouteDetailId(erpProcessRouteDetailId); //工艺路线_工序明细ID
                        newVProductionWorkProcedureDetail.setProcedureId(routeDetail.getWorkId());
                        newVProductionWorkProcedureDetail.setProcedureName(routeDetail.getWorkName());
                        newVProductionWorkProcedureDetail.setStatus(0);
                        procedureDetails.add(newVProductionWorkProcedureDetail);
                    });

                    newVProductionDispatchMain.setProcedureDetails(procedureDetails);
                    /** 保存 派工单*/
                    productionDispatchMainService.saveDispatch(newVProductionDispatchMain);
                    /** 自动审核 派工单*/
                    productionDispatchMainService.examine(newVProductionDispatchMain.getId(),1);
                    vProductionDispatchMain = newVProductionDispatchMain;
                }
                /** 查询派工明细ID */
                Integer productionWorkProcedureDetailId = null;
                List<VProductionWorkProcedureDetail> procedureDetails = vProductionDispatchMain.getProcedureDetails();
                if(null != procedureDetails){
                    Optional<VProductionWorkProcedureDetail> first = procedureDetails.stream().filter(f -> f.getProcessRouteDetailId().equals(erpProcessRouteDetailId)).findFirst();
                    if(!first.isPresent())throw new NuoNiuException("查询不到派工明细");
                    productionWorkProcedureDetailId =  first.get().getId().intValue();
                }else{
                    List<VProductionWorkProcedureDetailVo> procedureDetails1 = productionDispatchMainVo.getProcedureDetails();
                    if(null == procedureDetails1)throw new NuoNiuException("查询不到派工明细");
                    Optional<VProductionWorkProcedureDetailVo> first = procedureDetails1.stream().filter(f -> f.getProcessRouteDetailId().equals(erpProcessRouteDetailId)).findFirst();
                    if(!first.isPresent())throw new NuoNiuException("查询不到派工明细");
                    productionWorkProcedureDetailId =  first.get().getId().intValue();
                }

                /** 组装工序汇报*/
                ErpWorkProcedureCardDetail erpWorkProcedureCardDetail = new ErpWorkProcedureCardDetail();
                erpWorkProcedureCardDetail.setInventoryId(workDetail.getInventoryId().longValue());
                erpWorkProcedureCardDetail.setProductionWorkMainId(vProductionDispatchMain.getId());
                // TODO 去掉 派工单 单据
//                erpWorkProcedureCardDetail.setProductionWorkDetailId(vProductionDispatchMain.getVoucherCode());
                erpWorkProcedureCardDetail.setProductionWorkProcedureDetailId(productionWorkProcedureDetailId);
                erpWorkProcedureCardDetail.setProcedureId(processRouteDetail.getWorkId());
                erpWorkProcedureCardDetail.setProcedureName(processRouteDetail.getWorkName());
                erpWorkProcedureCardDetail.setWorkerId(userInfo.getUserId());
                erpWorkProcedureCardDetail.setWorkerName(userInfo.getRealName());
                erpWorkProcedureCardDetail.setUnitName(workDetail.getBaseUnitName());
                erpWorkProcedureCardDetail.setQualifiedQuantity(BigDecimal.ONE);
                erpWorkProcedureCardDetail.setUnqualifiedQuantity(BigDecimal.ZERO);
                erpWorkProcedureCardDetail.setReworkQuantity(BigDecimal.ZERO);
                erpWorkProcedureCardDetail.setScrapQuantity(BigDecimal.ZERO);
                /** 保存 工序汇报*/
                createCardDetail(erpWorkProcedureCardDetail,null);
                successMatchCodes.add(barCode);
            }catch (Exception e){
                String msg = "";
                if(e instanceof NuoNiuException){
                    msg = ((NuoNiuException) e).getMsg();
                }else{
                    msg = "汇报失败！";
                }
                failMatchCodes.add( barCode + ": "+ msg );
            }

        });
        return reportResult;
    }

    @Override
    public List<ProcedureCardDetailVo> listByIds(List<Long> ids) {
        UserInfo userInfo = UserThreadLocal.get();
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        List<ProcedureCardDetailVo> procedureCardDetailVos = baseMapper.listByIds(userInfo.getCompanyId(), currentAccountId, ids);
        return procedureCardDetailVos;
    }

    @Override
    public List<ErpWorkProcedureCardDetail> getSimpleStatusByIds(List<Long> ids) {
        UserInfo userInfo = UserThreadLocal.get();
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        QueryWrapper<ErpWorkProcedureCardDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("company_id",userInfo.getCompanyId());
        queryWrapper.eq("account_id",currentAccountId);
        queryWrapper.in("id",ids);
        queryWrapper.select("id","report_code","status");
        List<ErpWorkProcedureCardDetail> list = list(queryWrapper);
        if(ids.size() != list.size())throw new NuoNiuException("参数错误，请重新选择");
        return list;
    }

    @Override
    public void batchExamine(List<Long> ids, Integer status) {
        List<ErpWorkProcedureCardDetail> simpleStatusByIds = getSimpleStatusByIds(ids);
        if(null == simpleStatusByIds || simpleStatusByIds.size() == 0)throw new NuoNiuException("参数错误");
        if (1 == status){
//            String collect = simpleStatusByIds.stream().filter(f -> f.getStatus() > 0).map(ErpWorkProcedureCardDetail::getReportCode).collect(Collectors.joining());
//            if (StringUtils.isNotBlank(collect))throw new NuoNiuException("汇报编号：" + collect + "的记录已经审核了");
        }else if(0 == status){
            String warnMessage = "";
//            String collect1 = simpleStatusByIds.stream().filter(f -> f.getStatus() == 2).map(ErpWorkProcedureCardDetail::getReportCode).collect(Collectors.joining());
//            if (StringUtils.isNotBlank(collect1)){
//                warnMessage += "汇报编号：" + collect1 + "的记录已经核算了；";
//            }
//            String collect2 = simpleStatusByIds.stream().filter(f -> f.getStatus() == 0).map(ErpWorkProcedureCardDetail::getReportCode).collect(Collectors.joining());
//            if (StringUtils.isNotBlank(collect2)){
//                warnMessage += "汇报编号：" + collect2 + "的记录未审核；";
//            }
            if(StringUtils.isNotBlank(warnMessage))throw new NuoNiuException(warnMessage + "不能弃审");
        }else{
            throw new NuoNiuException("参数错误");
        }
        UpdateWrapper<ErpWorkProcedureCardDetail> updateWrapper = new UpdateWrapper<>();
        updateWrapper.in("id",ids);
        updateWrapper.set("status",status);
        update(updateWrapper);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void batchDelete(List<Long> ids) {
        List<ErpWorkProcedureCardDetail> simpleStatusByIds = getSimpleStatusByIds(ids);
//        String collect = simpleStatusByIds.stream().filter(f -> f.getStatus() > 0).map(ErpWorkProcedureCardDetail::getReportCode).collect(Collectors.joining());
//        if (StringUtils.isNotBlank(collect))throw new NuoNiuException("汇报编号：" + collect + "的记录已经审核了，不能删除");
        ids.forEach(id->delete(id));
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void delete(Long id) {
        ErpWorkProcedureCardDetail cardDetail = getById(id);
        if (null  == cardDetail)throw new NuoNiuException("删除失败,查询不到汇报记录");
        boolean b = removeById(id);
        if(b){
            /** 根据生产加工单 工序明细ID 获取加工工序详情*/
            VProductionWorkProcedureDetailVo vProductionWorkProcedureDetailVo = productionWorkProcedureDetailService.getVProductionWorkProcedureDetailVo(cardDetail.getProductionWorkProcedureDetailId());
            Integer status = vProductionWorkProcedureDetailVo.getStatus();
            if(status > 0)throw new NuoNiuException("该工序已经不能汇报了");
//            VProductionDispatchMain dispatchMain = productionDispatchMainService.getById(vProductionWorkProcedureDetailVo.getProductionDispatchId());
            VProductionDispatchMain dispatchMain = new VProductionDispatchMain();
            BigDecimal dispatchInventoryQuantity = dispatchMain.getDispatchInventoryQuantity();
            VProductionWorkProcedureDetail vProductionWorkProcedureDetail = new VProductionWorkProcedureDetail();
            /** 更新 本次工序 执行情况*/
            vProductionWorkProcedureDetail.setId(vProductionWorkProcedureDetailVo.getId());
            vProductionWorkProcedureDetail.setCumQualifiedQuantity(vProductionWorkProcedureDetailVo.getCumQualifiedQuantity().subtract(cardDetail.getQualifiedQuantity()));
            vProductionWorkProcedureDetail.setCumUnqualifiedQuantity(vProductionWorkProcedureDetailVo.getCumUnqualifiedQuantity().subtract(cardDetail.getUnqualifiedQuantity()));
            vProductionWorkProcedureDetail.setCumReworkQuantity(vProductionWorkProcedureDetailVo.getCumReworkQuantity().subtract(cardDetail.getReworkQuantity()));
            if(10 == status ){
                BigDecimal cumQualifiedQuantity = vProductionWorkProcedureDetail.getCumQualifiedQuantity();
                BigDecimal cumReworkQuantity = vProductionWorkProcedureDetail.getCumReworkQuantity();
                BigDecimal total = cumQualifiedQuantity.add(cumReworkQuantity);
                if (total.compareTo(dispatchInventoryQuantity) < 0){
                    vProductionWorkProcedureDetail.setStatus(0); //进行中
                }
            }
            productionWorkProcedureDetailService.updateById(vProductionWorkProcedureDetail);
            /** 如果是尾工序，更新 派工单完成数量*/
            if (2 == vProductionWorkProcedureDetailVo.getWorkFlag()){
                // 校验 是否生成 完工单
                VProductionFinishMain vProductionFinishMain = productionFinishMainService.getByCardDetailId(id);
                if ( null != vProductionFinishMain ){
//                    if (vProductionFinishMain.getVoucherState() > 0)throw new NuoNiuException("由此工序汇报(汇报单号："+cardDetail.getReportCode()+")生成的完工单(单据号："+vProductionFinishMain.getVoucherCode()+")已经审核，不能删除");
                    productionFinishMainService.deleteById(vProductionFinishMain.getId());
                }

//                BigDecimal finishInventoryQuantity = dispatchMain.getFinishInventoryQuantity();
//                if(null == finishInventoryQuantity || finishInventoryQuantity.compareTo(cardDetail.getQualifiedQuantity().add(cardDetail.getReworkQuantity())) < 0 ){
//                    throw new NuoNiuException("完成数量数据异常，请联系管理员");
//                }
//                productionDispatchMainService.updateFinishInventoryQuantity(dispatchMain.getId(),finishInventoryQuantity.subtract(cardDetail.getQualifiedQuantity()).subtract(cardDetail.getReworkQuantity()));
            }

        }

    }

    @Override
    public String getReportCode(Integer workProcedureDetailId,String productionWorkCode) {

        UserInfo userInfo = UserThreadLocal.get();
        Integer currentAccountId = erpAccountService.getCurrentAccountId();

        Integer maxSerialNumber = baseMapper.getMaxSerialNumber(userInfo.getCompanyId(), currentAccountId, workProcedureDetailId);
        if(null == maxSerialNumber) {
            maxSerialNumber = 1;
        }
        String serialNumberStr = String.format("%04d", maxSerialNumber );
        String reportCode = productionWorkCode + serialNumberStr;
        return reportCode;
    }

    @Override
    public void getAndSetReportCode(ErpWorkProcedureCardDetail erpWorkProcedureCardDetail, Integer workProcedureDetailId, String productionWorkCode) {
        UserInfo userInfo = UserThreadLocal.get();
        Integer currentAccountId = erpAccountService.getCurrentAccountId();

        Integer maxSerialNumber = baseMapper.getMaxSerialNumber(userInfo.getCompanyId(), currentAccountId, workProcedureDetailId);
        if(null == maxSerialNumber) {
            maxSerialNumber = 1;
        }else{
            maxSerialNumber++;
        }
        String serialNumberStr = String.format("%04d", maxSerialNumber );  //字符串补位0
        String reportCode = productionWorkCode + serialNumberStr;
        erpWorkProcedureCardDetail.setSerialNumber(maxSerialNumber);
//        erpWorkProcedureCardDetail.setReportCode(reportCode);
    }

    @Override
    public int sumByProductionDispatchId(Long productionDispatchId) {
        UserInfo userInfo = UserThreadLocal.get();
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        int sum = baseMapper.sumByProductionDispatchId(userInfo.getCompanyId(), currentAccountId, productionDispatchId);
        return sum;
    }


    @Override
    public List<ProcedureCardDetailVo> listProcedureCardDetailVoMobile(Integer workProcedureDetailId) {
        UserInfo userInfo = UserThreadLocal.get();
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        List<ProcedureCardDetailVo> procedureCardDetailVos = baseMapper.listProcedureCardDetailVoMobile(userInfo.getCompanyId(), currentAccountId, workProcedureDetailId);
        return procedureCardDetailVos;
    }

    /***************************************** 2022 - 01 - 25 ************************************************/

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void deleteByOrderId(Long orderId) {
        /**  1.更新 加工单 工序明细 累计 汇报情况*/
        List<ErpWorkProcedureCardDetail> erpWorkProcedureCardDetails = this.listQuantityVo(orderId);
        this.updateProductionWorkProcedureCumQuantity(new ArrayList<>(),erpWorkProcedureCardDetails);
        /**  2.筛选 尾工序*/
        erpWorkProcedureCardDetails.forEach(f-> {
            if(2 == f.getProcedureFlag()){
                Long id = f.getId();
                //校验 是否生成 完工单
                VProductionFinishMain vProductionFinishMain = productionFinishMainService.getByCardDetailId(id);
                if ( null != vProductionFinishMain ){
                    if (vProductionFinishMain.getVoucherState() > 0)throw new NuoNiuException("由 工序汇报 自动 生成的完工单(单据号："+vProductionFinishMain.getVoucherCode()+")已经审核，不能删除");
                    productionFinishMainService.deleteById(vProductionFinishMain.getId());
                }
            }
        });

        UserInfo userInfo = UserThreadLocal.get();
        QueryWrapper<ErpWorkProcedureCardDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_id",orderId);
        queryWrapper.eq("company_id",userInfo.getCompanyId());
        remove(queryWrapper);

    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void batchSaveDetails(ErpWorkProcedureCardMain erpWorkProcedureCardMain) {
        UserInfo userInfo = UserThreadLocal.get();
        Integer currentAccountId = erpAccountService.getCurrentAccountId();
        Long mainId = erpWorkProcedureCardMain.getId();
        List<ErpWorkProcedureCardDetail> orderDetailList = erpWorkProcedureCardMain.getOrderDetailList();
        orderDetailList.stream().forEach(item->{
            Integer wagesType = item.getWagesType();
            item.setCompanyId(userInfo.getCompanyId());
            item.setAccountId(currentAccountId);
            item.setOrderId(erpWorkProcedureCardMain.getId().intValue());
            if(null == item.getQualifiedQuantity() || item.getQualifiedQuantity().compareTo(BigDecimal.ZERO) < 0)item.setQualifiedQuantity(BigDecimal.ZERO);
            if(null == item.getUnqualifiedQuantity() || item.getUnqualifiedQuantity().compareTo(BigDecimal.ZERO) < 0)item.setUnqualifiedQuantity(BigDecimal.ZERO);
            if(null == item.getReworkQuantity() || item.getReworkQuantity().compareTo(BigDecimal.ZERO) < 0)item.setReworkQuantity(BigDecimal.ZERO);
            if(null == item.getScrapQuantity() || item.getScrapQuantity().compareTo(BigDecimal.ZERO) < 0)item.setScrapQuantity(BigDecimal.ZERO);
            if(1 == wagesType){
                if(item.getQualifiedQuantity().add(item.getUnqualifiedQuantity()).add(item.getReworkQuantity()).add(item.getScrapQuantity()).compareTo(BigDecimal.ZERO) == 0){
                    throw new NuoNiuException("请填写汇报数量");
                }
            }else if(2 == wagesType) {
                BigDecimal workHour = item.getWorkHour();
                if (null == workHour)throw new NuoNiuException("请填报工时");
            }
            if(null == item.getProcedureFlag())throw new NuoNiuException("工序标识不能为空");
        });

        List<ErpWorkProcedureCardDetail> erpWorkProcedureCardDetails = null;
        if( null != mainId){
            /** 1.查询之前的汇报数量明细 */
            erpWorkProcedureCardDetails = this.listQuantityVo(mainId);
            List<Long> beforeOldDetailIds = erpWorkProcedureCardDetails.stream().map(ErpWorkProcedureCardDetail::getId).collect(Collectors.toList());
            List<Long> afterOldDetailIds = orderDetailList.stream().map(ErpWorkProcedureCardDetail::getId).collect(Collectors.toList());
            /** 2.删除 需要删除的明细 */
            boolean removeAll = beforeOldDetailIds.removeAll(afterOldDetailIds);
            if(removeAll && beforeOldDetailIds.size() > 0){
                this.removeByIds(beforeOldDetailIds);
            }
        }
        /** 3.计算 加工单工序明细 累计 汇报数量 情况 */
        this.updateProductionWorkProcedureCumQuantity(orderDetailList,erpWorkProcedureCardDetails);

        /** 4.计算工资*/
        this.calculateSalary(orderDetailList);

        /** 5.批量保存 汇报明细*/
        boolean b = this.saveOrUpdateBatch(orderDetailList);

        /** 6.尾工序 生产完工单*/
        if( b ){
            List<ErpWorkProcedureCardDetail> lastFlagDetails = orderDetailList.stream().filter(f -> f.getProcedureFlag() == 2).collect(Collectors.toList());
            if(lastFlagDetails.size() > 0){
                lastFlagDetails.forEach(this::saveVProductionFinishMainFromCardDetail);
            }
        }
    }

    @Override
    public List<ErpWorkProcedureCardDetail> listQuantityVo(Long orderId) {
        UserInfo userInfo = UserThreadLocal.get();
        QueryWrapper<ErpWorkProcedureCardDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("company_id",userInfo.getCompanyId());
        queryWrapper.eq("order_id",orderId);
        queryWrapper.select("id","order_id","production_work_procedure_detail_Id","procedure_flag","qualified_quantity","unqualified_quantity","rework_quantity","scrap_quantity");
        return list(queryWrapper);
    }

    /**
     * 更新 加工单 工序明细 累计 汇报情况
     * @param beforeList
     * @param afterList
     */
    @Override
    public void updateProductionWorkProcedureCumQuantity(List<ErpWorkProcedureCardDetail> afterList, List<ErpWorkProcedureCardDetail> beforeList) {
        UserInfo userInfo = UserThreadLocal.get();
        Map<Integer,ProductionWorkReportQuantityVo> productionWorkProcedureDetailMap = new HashMap<>();
        /** 加法 */
        afterList.forEach(newDetail->{
            Integer productionWorkProcedureDetailId = newDetail.getProductionWorkProcedureDetailId();
            if(null == productionWorkProcedureDetailId)return;
            ProductionWorkReportQuantityVo quantityVo = productionWorkProcedureDetailMap.get(productionWorkProcedureDetailId);
            if(null == quantityVo){
                quantityVo = new ProductionWorkReportQuantityVo();
                quantityVo.setProductionWorkProcedureDetailId(productionWorkProcedureDetailId);
                productionWorkProcedureDetailMap.put(productionWorkProcedureDetailId,quantityVo);
            }
            quantityVo.setOffsetQualifiedQuantity( quantityVo.getOffsetQualifiedQuantity().add(newDetail.getQualifiedQuantity()) );
            quantityVo.setOffsetUnqualifiedQuantity( quantityVo.getOffsetUnqualifiedQuantity().add(newDetail.getUnqualifiedQuantity()) );
            quantityVo.setOffsetReworkQuantity( quantityVo.getOffsetReworkQuantity().add(newDetail.getReworkQuantity()) );
            quantityVo.setOffsetScrapQuantity( quantityVo.getOffsetScrapQuantity().add(newDetail.getScrapQuantity()) );
        });
        /** 减法 */
        if(null != beforeList && beforeList.size() > 0){
            beforeList.forEach(oldDetail->{
                Integer productionWorkProcedureDetailId = oldDetail.getProductionWorkProcedureDetailId();
                ProductionWorkReportQuantityVo quantityVo = productionWorkProcedureDetailMap.get(productionWorkProcedureDetailId);
                if(null == quantityVo){
                    quantityVo = new ProductionWorkReportQuantityVo();
                    quantityVo.setProductionWorkProcedureDetailId(productionWorkProcedureDetailId);
                    productionWorkProcedureDetailMap.put(productionWorkProcedureDetailId,quantityVo);
                }
                quantityVo.setOffsetQualifiedQuantity( quantityVo.getOffsetQualifiedQuantity().subtract(oldDetail.getQualifiedQuantity()) );
                quantityVo.setOffsetUnqualifiedQuantity( quantityVo.getOffsetUnqualifiedQuantity().subtract(oldDetail.getUnqualifiedQuantity()) );
                quantityVo.setOffsetReworkQuantity( quantityVo.getOffsetReworkQuantity().subtract(oldDetail.getReworkQuantity()) );
                quantityVo.setOffsetScrapQuantity( quantityVo.getOffsetScrapQuantity().subtract(oldDetail.getScrapQuantity()) );
            });
        }
        /** 查询 并 更新 */
        Set<Integer> productionWorkProcedureDetailIds = productionWorkProcedureDetailMap.keySet();
        if(productionWorkProcedureDetailIds.size() > 0){
            QueryWrapper<VProductionWorkProcedureDetail> procedureDetailQueryWrapper = new QueryWrapper<>();
            procedureDetailQueryWrapper.select("id","cum_qualified_quantity","cum_unqualified_quantity","cum_rework_quantity","cum_scrap_quantity");
            procedureDetailQueryWrapper.eq("company_id",userInfo.getCompanyId());
            procedureDetailQueryWrapper.in("id",productionWorkProcedureDetailIds);
            List<VProductionWorkProcedureDetail> productionWorkProcedureDetailList = productionWorkProcedureDetailService.list(procedureDetailQueryWrapper);
            /** 赋值*/
            productionWorkProcedureDetailList.forEach(procedureDetail -> {
                ProductionWorkReportQuantityVo quantityVo = productionWorkProcedureDetailMap.get(procedureDetail.getId().intValue());
                procedureDetail.setCumQualifiedQuantity(procedureDetail.getCumQualifiedQuantity().add(quantityVo.getOffsetQualifiedQuantity()));
                procedureDetail.setCumUnqualifiedQuantity(procedureDetail.getCumUnqualifiedQuantity().add(quantityVo.getOffsetUnqualifiedQuantity()));
                procedureDetail.setCumReworkQuantity(procedureDetail.getCumReworkQuantity().add(quantityVo.getOffsetReworkQuantity()));
                procedureDetail.setCumScrapQuantity(procedureDetail.getCumScrapQuantity().add(quantityVo.getOffsetScrapQuantity()));
            });
            /** 更新*/
            productionWorkProcedureDetailService.updateBatchById(productionWorkProcedureDetailList);
        }
    }

    /**
     * 计算工资
     * @param detailList
     */
    @Override
    public void calculateSalary(List<ErpWorkProcedureCardDetail> detailList) {
        List<Integer> detailIds = detailList.stream().map(ErpWorkProcedureCardDetail::getProcedureId).collect(Collectors.toList());
        /** 查询 最新 工价 */
        List<ProcedureLastPriceVo> procedureLastPriceVos = procedurePriceDetailService.listProcedureLastPriceVo(detailIds);
        Map<String,ProcedureLastPriceVo> procedureLastPriceVoMap = new HashMap<>();
        procedureLastPriceVos.forEach(priceVo->{
            Integer procedureId = priceVo.getProcedureId();
            procedureLastPriceVoMap.put(procedureId.toString(),priceVo);
            Integer processRouteDetailId = priceVo.getProcessRouteDetailId();
            if(null != processRouteDetailId){
                procedureLastPriceVoMap.put(procedureId+ "_" + processRouteDetailId,priceVo);
            }
        });
        /** 计算 工资 */
        detailList.forEach(detail->{
            Integer procedureId = detail.getProcedureId();
            String procedureIdKey = procedureId  + "";
            String processRouteDetailIdKey = procedureIdKey;
            Integer processRouteDetailId = detail.getProcessRouteDetailId();
            if(null != processRouteDetailId){
                processRouteDetailIdKey = processRouteDetailIdKey + "_" + processRouteDetailId;
            }
            ProcedureLastPriceVo priceVo = procedureLastPriceVoMap.get(processRouteDetailIdKey);
            if(null == priceVo){
                priceVo = procedureLastPriceVoMap.get(procedureIdKey);
            }
            if(null == priceVo)return;
            //设置 工价明细ID (工价参考)
            detail.setProcedurePriceDetailId(priceVo.getProcessRouteDetailId());
            BigDecimal qualifiedPrice = null != detail.getQualifiedPrice() ? detail.getQualifiedPrice() : null == processRouteDetailId ? priceVo.getQualifiedPrice() : priceVo.getLastQualifiedPrice();
            BigDecimal unqualifiedPrice = null != detail.getUnqualifiedPrice() ? detail.getUnqualifiedPrice() : null == processRouteDetailId ? priceVo.getUnqualifiedPrice() : priceVo.getLastUnqualifiedPrice();
            BigDecimal reworkPrice = null != detail.getReworkPrice() ? detail.getReworkPrice() : null == processRouteDetailId ? priceVo.getReworkPrice() : priceVo.getLastReworkPrice();
            BigDecimal scrapPrice = null != detail.getScrapPrice() ? detail.getScrapPrice() : null == processRouteDetailId ? priceVo.getScrapPrice() : priceVo.getLastScrapPrice();
            Integer wagesType = detail.getWagesType();
            if (null != wagesType){
                // 1.计件
                if (1 == wagesType){

                    BigDecimal workerWages = new BigDecimal(0);
                    if(null != qualifiedPrice){
                        workerWages = workerWages.add(qualifiedPrice.multiply(detail.getQualifiedQuantity()));
                    }
                    if (null != reworkPrice){
                        workerWages = workerWages.add(reworkPrice.multiply(detail.getReworkQuantity()));
                    }
                    if (null != scrapPrice){
                        workerWages = workerWages.add(scrapPrice.multiply(detail.getScrapQuantity()));
                    }
                    if (null != unqualifiedPrice){
                        workerWages = workerWages.add(unqualifiedPrice.multiply(detail.getUnqualifiedQuantity()));
                    }
                    detail.setWorkerWages(workerWages);

                }
                else if(2 == wagesType){
                    BigDecimal workHour = detail.getWorkHour();
                    BigDecimal workHourPrice = detail.getWorkHourPrice();
                    BigDecimal workerWages = new BigDecimal(0);
                    if (null == workHour)throw new NuoNiuException("请填报工时");
                    if(null != workHourPrice){
                        workerWages = workerWages.add(workHourPrice.multiply(workHour));
                    }
                    detail.setWorkerWages(workerWages);
                }
            }


        });
    }


}
